// 
//  Copyright 2011  reda
// 
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
// 
//        http://www.apache.org/licenses/LICENSE-2.0
// 
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using ManiacMusicManager.Data.Core;
using ManiacMusicManager.Data.Utils;
using ManiacMusicManager.Data.DAO.Wrapper;

namespace ManiacMusicManager.Data.DAO.Ifaces
{
	public interface IDAO : IDisposable
	{
		/// <summary>
		/// Encapsule l'objet courant dans un DAOWrapper pour pouvoir manipuler des réfenrences à Entity
		/// </summary>
		/// <returns>
		/// Objet DAO Wrapper
		/// </returns>
		IDAO<Entity> Wrap();
	}
	
	/// <summary>
	/// Interface génerique d'un manager d'entitées, contient les opération DAO de base
	/// </summary>
	public interface IDAO<T>: IDAO
		where T : Entity
	{
		#region Update Database
		/// <summary>
		/// Enregistre dans la base de données l'objet <paramref name="obj"/>
		/// </summary>
		/// <param name="obj">
		/// Objet <typeparamref name="T"/> à persister
		/// </param>
		int Save(T obj);
		
		/// <summary>
		/// Met à jour dans la base de données un objet
		/// </summary>
		/// <param name="obj">
		/// Objet <typeparamref name="T"/> à mettre à jour
		/// </param>
		void Update(T obj);
		
		/// <summary>
		/// Retirer un objet de la base de données
		/// </summary>
		/// <param name="obj">
		/// Objet <typeparamref name="T"/> à retirer
		/// </param>
		void Delete(T obj);
		
		/// <summary>
		/// Supprime un objet de la base de données à partir de son id
		/// </summary>
		/// <param name="id">
		/// Identifiant de l'objet persistant
		/// </param>
		void Delete(int id);
		
		/// <summary>
		/// Enregistre un objet ou le met à jour si existe déja dans la base de données
		/// </summary>
		/// <param name="obj">
		/// Objet <typeparamref name="T"/> à enregistrer ou mettre à jour
		/// </param>
		void SaveOrUpdate(T obj);
		
		/// <summary>
		/// Charge un objet <typeparamref name="T"/> depuis la base de données à partir de son id
		/// </summary>
		/// <param name="id">
		/// Identifiant unique de l'objet
		/// </param>
		/// <returns>
		/// Objet construit à partir de la base de données ou null si celui-ci n'existe pas
		/// </returns>
		T Get(int id);
		
		/// <summary>
		/// Supprime toutes les entitées de type <typeparamref name="T"/> de la base de données
		/// </summary>
		void Clear();
		#endregion
		
		#region RequestManagement
		
		/// <summary>
		/// Retourne un élement unique à partir d'une énumeration d'objet
		/// </summary>
		/// <param name="coll">
		/// Collection d'objets
		/// </param>
		/// <returns>
		/// Elément unique de <paramref name="coll"/>, si elle contient plus ou moins de 1 élement renvoie <c>null</c>
		/// </returns>
		T GetOneResult(IEnumerable<T> coll);
		
		/// <summary>
		/// Renvoie un objet utiliseable avec Linq to Hibernate, à utiliser comme collection lors d'une requête Linq
		/// </summary>
		/// <returns>
		/// Objet utilisable par Linq
		/// </returns>
		IQueryable<T> Linq();
		
		/// <summary>
		/// Selectionne un ensemble d'éléments à partir d'une requête Linq
		/// </summary>
		/// <param name="query">
		/// Requête Linq
		/// </param>
		/// <returns>
		/// Liste des résultats de la requête
		/// </returns>
		IEnumerable<T> SelectByQuery(IQueryable<T> query);
		
		/// <summary>
		/// Retourne le premier élement resultant d'une requête Linq
		/// </summary>
		/// <param name="query">
		/// Requête Linq
		/// </param>
		/// <returns>
		/// Résultat de la requête ou <c>null</c> si le résultat est non unique
		/// </returns>
		T GetByQuery(IQueryable<T> query);
		#endregion

		#region Filters
		/// <summary>
		/// Retourne une requête qui filtre les objets selon un texte
		/// </summary>
		/// <param name="strGet">
		/// Expression qui d'un objet retourne la valeur sur laquelle s'appliquera le filtre
		/// </param>
		/// <param name="value">
		/// Valeur critere du filtre
		/// </param>
		/// <param name="options">
		/// Options de recherche
		/// </param>
		/// <returns>
		/// Requête d'objets réutilisable
		/// </returns>
		IQueryable<T> FilterOnText(Expression<Func<T, string>> strGet, string value, StringSearchOptions options);
		
		/// <summary>
		/// Retourne une requête qui filte les objets selon une valeur entiere comprise entre <paramref name="minValue"/> et <paramref name="maxValue"/>
		/// </summary>
		/// <param name="intGet">
		/// Expression qui d'un objet retourne la valeur sur laquelle s'appliquera le filtre
		/// </param>
		/// <param name="minValue">
		/// Valeur minimale (inclue)
		/// </param>
		/// <param name="minValue">
		/// Valeur maximale (inclue)
		/// </param>
		/// <returns>
		/// Requête d'objets réutilisable
		/// </returns>
		IQueryable<T> FilterOnInteger(Expression<Func<T, int>> intGet, int minValue, int maxValue);
		
		/// <summary>
		/// Retourne une requête qui filte les objets selon un texte dans une liste
		/// </summary>
		/// <param name="lstGet">
		/// Expression qui d'un objet retourne la valeur sur laquelle s'appliquera le filtre
		/// </param>
		/// <param name="value">
		/// Valeur critere du filtre
		/// </param>
		/// <param name="options">
		/// Options de recherche
		/// </param>
		/// <returns>
		/// Requête d'objets réutilisable
		/// </returns>
		IQueryable<T> FilterOnStringList(Expression<Func<T, IEnumerable<string>>> lstGet, string value, StringSearchOptions options);
		
		/// <summary>
		/// Retourne une requête qui filte les objets selon une valeur entiere égale à  <paramref name="value"/>
		/// </summary>
		/// <param name="intGet">
		/// Expression qui d'un objet retourne la valeur sur laquelle s'appliquera le filtre
		/// </param>
		/// <param name="value">
		/// Valeur critere exacte
		/// </param>
		/// <returns>
		/// Requête d'objets réutilisable
		/// </returns>
		IQueryable<T> FilterOnInteger(Expression<Func<T, int>> intGet, int value);
		#endregion
		
		#region General Queries
		/// <summary>
		/// Cherche dans la base de données les objets dont le nom correspond à <paramref name="name"/> avec les options <paramref name="options"/>
		/// </summary>
		/// <param name="name">
		/// Nom de l'entité qu'on recherche
		/// </param>
		/// <param name="options">
		/// Options de recherche
		/// </param>
		/// <returns>
		/// Enumération des résultats
		/// </returns>
		IEnumerable<T> SelectByName(string name, StringSearchOptions options);
		
		/// <summary>
		/// Cherche dans la base de données les objets dont le nom correspond à <paramref name="name"/> (recherche des noms contenant <paramref name="name"/> en ignorant la casse)
		/// </summary>
		/// <param name="name">
		/// Nom qu'on recherche
		/// </param>
		/// <returns>
		/// Enumération des résultats
		/// </returns>
		IEnumerable<T> SelectByName(string name);
		
		/// <summary>
		/// Cherche dans la base de données l'objets dont le nom correspond à <paramref name="name"/> (recherche du nom exact <paramref name="name"/> en ignorant la casse)
		/// </summary>
		/// <param name="name">
		/// Nom qu'on recherche
		/// </param>
		/// <returns>
		/// Résultat ou <c>null</c> si le résultat est non unique
		/// </returns>
		T GetByName(string name);
		
		/// <summary>
		/// Cherche dans la base de données les objets dont les commentaires contiennent tous les mots <paramref name="mots"/>
		/// </summary>
		/// <param name="mots">
		/// Mots à rechercher
		/// </param>
		/// <returns>
		/// Resultat de la requete
		/// </returns>
		IEnumerable<T> SelectByComment(params string[] mots);
		#endregion
		
		/// <summary>
		/// Construit une énumeration Thread Safe à partir d'une énumeration à partir d'une énumeration non Thread Safe
		/// </summary>
		/// <param name="list">
		/// Enumération non Thread Safe
		/// </param>
		/// <returns>
		/// Enumeration Thread Safe résultante
		/// </returns>
		IEnumerable<T> MakeSafe(IEnumerable<T> list);
	}
}

